package frontend;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.sql.SQLException;
import java.util.List;
import java.io.IOException;

public class ThreadClienteFront extends Thread {
   
    private Socket socketClienteFront;
    private ObjectInputStream flujoEntrada;
    private ObjectOutputStream flujoSalida;
    private List <Socket> listaClientesFront;
    private ObjectInputStream tflujoEntradaCatalogo;
    private ObjectOutputStream tflujoSalidaCatalogo;
    private ObjectInputStream tflujoEntradaPedidos;
    private ObjectOutputStream tflujoSalidaPedidos;
    private ObjectInputStream tflujoEntradaDNS;
    private ObjectOutputStream tflujoSalidaDNS;
    private Object TS;
    private Object Cordinador;
    private Socket socketCatalogo;
    private Socket socketPedidos;
    
	private String ipServerCatalogo = "localhost";
	private String ipServerPedidos = "localhost";
	private int puertoCatalogo = 5000;
	private int puertoPedidos = 5001;
    
    
    public ThreadClienteFront(Socket socketClient, List<Socket> listaClientsFront,
    		                  ObjectInputStream InputDNS, ObjectOutputStream OutputDNS,
    		                  Object TimeS, Object Coord) throws IOException {
        this.socketClienteFront = socketClient;
        this.socketCatalogo = new Socket(ipServerCatalogo,puertoCatalogo);
        this.socketPedidos = new Socket(ipServerPedidos,puertoPedidos);
        this.TS = TimeS;
        this.Cordinador = Coord;
        this.tflujoSalidaCatalogo = new ObjectOutputStream(socketCatalogo.getOutputStream());
        this.tflujoEntradaCatalogo = new ObjectInputStream(socketCatalogo.getInputStream());
        this.tflujoSalidaPedidos = new ObjectOutputStream(socketPedidos.getOutputStream());
        this.tflujoEntradaPedidos= new ObjectInputStream(socketPedidos.getInputStream());
        this.tflujoSalidaDNS = OutputDNS;
        this.tflujoEntradaDNS = InputDNS;
        this.flujoSalida = new ObjectOutputStream(socketClient.getOutputStream());    
    	this.flujoEntrada = new ObjectInputStream(socketClient.getInputStream()); 
        this.listaClientesFront = listaClientsFront;

    }
   
    public void run () {
        try {
            while (true) {
                String mensaje = flujoEntrada.readUTF();
                System.out.println("FrontEnd: Ejecutando " + mensaje + "[threadId: " + this.getId() + "]");
                if ("getTime".equalsIgnoreCase(mensaje.substring(0,7))) {
                    try {
                    	sendToClient(getClientTime(),flujoSalida);
                	} catch (ClassNotFoundException e) {
                	    sendToClient("FrontEnd: Error getClientTime()",flujoSalida);
                		e.printStackTrace();
                	}
                } else if ("buyBook".equalsIgnoreCase(mensaje.substring(0,7))) {
                	try {
                		sendToClient(setComprarLibros(mensaje),flujoSalida);
                    } catch (ClassNotFoundException e) {
                    	sendToClient("FrontEnd: Error setComprarLibros()",flujoSalida);
                    	e.printStackTrace();
                    }
                  } else if ("EsCord".equalsIgnoreCase(mensaje.substring(0,6))) {
                	  this.Cordinador = true;
                	  System.out.println("FrontEnd: Se ha seteado el frontend como coordinador [threadId: " + this.getId() + "]");
                	  
                    } else {
                    	try {
                    		sendToClient(getListaLibros(mensaje),flujoSalida);
                		} catch (ClassNotFoundException e) {
                			sendToClient("FrontEnd: Error getListaLibros()",flujoSalida);
                			e.printStackTrace();
                		}
                	}
            }   
        }
        catch (IOException ex) {
        	System.out.println("FrontEnd: Un Cliente se ha desconectado [threadId: " + this.getId() + "]");
        	//ex.printStackTrace();
        }
        finally {
        	listaClientesFront.remove(this.socketClienteFront);
            cerrarFlujos();
        }
    }
    
    private void sendToClient(Object mensaje, ObjectOutputStream flujoSalida) {
        try {
            flujoSalida.writeObject(mensaje);
            flujoSalida.flush();
        }    
        catch (IOException ex) {
            System.out.println("FrontEnd: Error en sendToClient [threadId: " + this.getId() + "]");
            ex.printStackTrace();
	} 
    } 

    private void cerrarFlujos() { 
        try {
             flujoEntrada.close();
             flujoSalida.close();
             socketClienteFront.close();
        }
        catch (IOException ex) {
        	 System.out.println("FrontEnd: Error en cerrarFlujos [threadId: " + this.getId() + "]");
             ex.printStackTrace();
        }        
    }
    
    private Object recieveFrom(ObjectInputStream flujo) throws IOException, ClassNotFoundException {
		Object mensaje = null;
    	try {
			mensaje = flujo.readObject();
		}
		catch (IOException ex) {
			System.out.println("FrontEnd: Error en recieveFrom [threadId: " + this.getId() + "]");
			ex.printStackTrace();
		}
		return mensaje;
    }
    
    private void sendTo(ObjectOutputStream flujo, String mensaje) throws IOException {
        try {
        	flujo.writeUTF(mensaje);
        	flujo.flush();
        }
        catch (IOException ex) {
            System.out.println("FrontEnd: Error en sendTo [threadId: " + this.getId() + "]");
            ex.printStackTrace();
        }        
    }
    
    public Object setComprarLibros(String mensaje) throws IOException, ClassNotFoundException {
		sendTo(this.tflujoSalidaPedidos,mensaje);
        Object listaLibros = recieveFrom(this.tflujoEntradaPedidos);
	    return listaLibros;
	}   
    
	public Object getListaLibros(String mensaje) throws IOException, ClassNotFoundException {
		sendTo(this.tflujoSalidaCatalogo,mensaje);
        Object listaLibros = recieveFrom(this.tflujoEntradaCatalogo);
	    return listaLibros;
	}    
	
	public Object getClientTime() throws IOException, ClassNotFoundException {
		long clientTime = System.currentTimeMillis();
		String str = Long.toString(clientTime);
		//sendTo(this.tflujoSalidaDNS,str);
		return (Object) str;
	}    
}

